import os.path
import logging
import hashlib
import hmac
import base64
import logging

import webapp2
import webapp2_extras.jinja2
import webapp2_extras.sessions
import Crypto.Random
from google.appengine.api import users
from ..models.User import User
from ..models.Log import LogHandler
from .uri import Uri

root = os.path.normpath(os.path.join(
	os.path.dirname(__file__),
	'..',
	'..',
))

class ShopkeepApplication(webapp2.WSGIApplication):
	@staticmethod
	def handle_404(request, response, exception):
		logging.info(exception, exc_info=True)
		response.write('Need more SOSS on this page.')
		response.set_status(404)

	@staticmethod
	def handle_500(request, response, exception):
		logging.exception(exception)
		response.write('Looks like there\'s just too much SOSS on this page.')
		response.set_status(500)

	def __init__(self, *args, **kwargs):
		logger = logging.getLogger()
		logger.addHandler(LogHandler())

		if 'config' not in kwargs:
			kwargs['config'] = {}

		kwargs['config']['webapp2_extras.sessions'] = {}
		kwargs['config']['webapp2_extras.sessions']['cookie_name'] = 'shopkeep'
		with open(os.path.join(root, 'config', 'session.key')) as fp:
			kwargs['config']['webapp2_extras.sessions']['secret_key'] = fp.read()
		kwargs['config']['webapp2_extras.sessions']['session_max_age'] = 60 * 60 * 24 * 3
		kwargs['config']['webapp2_extras.sessions']['cookie_args'] = {
			'max_age': kwargs['config']['webapp2_extras.sessions']['session_max_age'],
			'secure': True,
			'httponly': True
		}

		kwargs['config']['webapp2_extras.jinja2'] = {}
		kwargs['config']['webapp2_extras.jinja2']['template_path'] = os.path.join(root, 'templates')
		#kwargs['config']['webapp2_extras.jinja2']['compiled_path'] = os.path.join(root, 'templates', 'compiled')

		super(ShopkeepApplication, self).__init__(*args, **kwargs)

		self.error_handlers[404] = self.handle_404
		self.error_handlers[500] = self.handle_500

class ShopkeepHandler(webapp2.RequestHandler):
	csrf = True

	def dispatch(self, *args, **kwargs):
		self.session_store = webapp2_extras.sessions.get_store(request=self.request)

		#if self.request.method != 'GET' and self.csrf and self.token != self.request.POST['token']:
		#	self.abort(400, detail='Bad CSRF token.')

		try:
			webapp2.RequestHandler.dispatch(self, *args, **kwargs)
		finally:
			self.session_store.save_sessions(self.response)

	def render_response(self, _template, context):
		context['user'] = User.getUser(users.get_current_user())
		context['login_url'] = users.create_login_url(self.request.url)
		context['logout_url'] = users.create_logout_url(self.request.url)
		context['uri'] = Uri(self.request.url)
		context['token'] = self.token
		context['returnto'] = Uri(context['uri'].query['returnto'][0]) if context['uri'].query.get('returnto') else ''
		rv = self.jinja2.render_template(_template, **context)
		self.response.write(rv)

	@webapp2.cached_property
	def token(self):
		token = self.session.get('token')
		if not token:
			self.session['token'] = token = base64.b64encode(Crypto.Random.get_random_bytes(512))
		return hmac.new(self.request.url, token, hashlib.sha512).hexdigest()

	@webapp2.cached_property
	def session(self):
		return self.session_store.get_session()

	@webapp2.cached_property
	def jinja2(self):
		return webapp2_extras.jinja2.get_jinja2(app=self.app)

	def handle_exception(self, exception, debug):
		logging.exception(exception)

		if isinstance(exception, webapp2.HTTPException):
			self.response.set_status(exception.code)
		elif isinstance(exception, ValueError):
			self.abort(400)
		else:
			self.response.set_status(500)
